package com.hellobike.haxing.modules.product.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.base.Strings;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.hellobike.haxing.modules.product.TreeNode;
import com.hellobike.haxing.modules.product.entity.Category;
import com.hellobike.haxing.modules.product.exception.ProductException;
import com.hellobike.haxing.modules.product.mapper.CategoryMapper;
import com.hellobike.haxing.modules.product.service.ICategoryService;
import com.hellobike.haxing.modules.product.util.MapUtil;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * @Description: 后台分类
 * @Author: haxing-boot
 * @Date:   2020-01-11
 * @Version: V1.0
 */
@Service
public class CategoryServiceImpl extends ServiceImpl<CategoryMapper, Category> implements ICategoryService {

	@Override
	public void addCategory(Category category) {
//		if(oConvertUtils.isEmpty(category.getParentId())){
//			category.setParentId(ICategoryService.ROOT_PID_VALUE);
//		}else{
//			//如果当前节点父ID不为空 则设置父节点的hasChildren 为1
//			Category parent = baseMapper.selectById(category.getParentId());
//			if(parent!=null && !"1".equals(parent.get())){
//				parent.set("1");
//				baseMapper.updateById(parent);
//			}
//		}

		checkNameRepeat(category.getName(), null);
		fillFileds(category);
		baseMapper.insert(category);
	}

	//检查分类名称是否重复
	private void checkNameRepeat(String name, Long selfId) {
		QueryWrapper<Category> queryWrapper = new QueryWrapper<>();
		queryWrapper.lambda().eq(Category::getName, name);
		Category sameNameCategory = baseMapper.selectOne(queryWrapper);
		if (sameNameCategory != null && !Objects.equals(sameNameCategory.getId(), selfId)) {
			throw new ProductException("与其他分类名称重复，请修改后再提交");
		}
	}

	//设置层级、序列号、编码等字段
	//编码规则：第1位：层级，第2-4位：一级分类序列号，第5-7位：二级分类序列号，第8-10位：三级分类序列号
	private void fillFileds(Category category) {
		Long parentId = category.getParentId() == null ? 0L : category.getParentId();
		Category parent = baseMapper.selectById(parentId);
		Integer level = parent == null ? 1 : parent.getLevel() + 1;
		Integer peerMaxSerial = baseMapper.getPeerMaxSerial(parentId);
		Integer serial = peerMaxSerial == null ? 1 : peerMaxSerial + 1;
		String code = null;
		if (level == 1) {
			code = "1" + Strings.padStart(serial.toString(), 3, '0') + "000000";
		} else if (level == 2) {
			code = "2" + parent.getCode().substring(1, 4) + Strings.padStart(serial.toString(), 3, '0') + "000";
		} else if (level == 3) {
			code = "3" + parent.getCode().substring(1, 7) + Strings.padStart(serial.toString(), 3, '0');
		}
		category.setParentId(parentId);
		category.setLevel(level);
		category.setSerial(serial);
		category.setCode(code);
		category.setUpdateTime(new Date());
	}
	
	@Override
	public void updateCategory(Category category) {
		Category entity = this.getById(category.getId());
		if(entity==null) {
			throw new ProductException("未找到对应实体");
		}
//		String old_pid = entity.getParentId();
//		String new_pid = category.getParentId();
//		if(!old_pid.equals(new_pid)) {
//			updateOldParentNode(old_pid);
//			if(oConvertUtils.isEmpty(new_pid)){
//				category.setParentId(ICategoryService.ROOT_PID_VALUE);
//			}
//			if(!ICategoryService.ROOT_PID_VALUE.equals(category.getParentId())) {
//				baseMapper.updateTreeNodeStatus(category.getParentId(), ICategoryService.HASCHILD);
//			}
//		}
		checkNameRepeat(category.getName(), category.getId());
		baseMapper.updateById(category);
	}
	
	@Override
	public void deleteCategory(Long id) {
		Category category = this.getById(id);
		if(category==null) {
			throw new RuntimeException("未找到对应实体");
		}
//		updateOldParentNode(category.getParentId());
		baseMapper.deleteById(id);
	}
	
	
	
	/**
	 * 根据所传pid查询旧的父级节点的子节点并修改相应状态值
	 * @param pid
	 */
	private void updateOldParentNode(String pid) {
		if(!ICategoryService.ROOT_PID_VALUE.equals(pid)) {
			Integer count = baseMapper.selectCount(new QueryWrapper<Category>().eq("parent_id", pid));
			if(count==null || count<=1) {
				baseMapper.updateTreeNodeStatus(pid, ICategoryService.NOCHILD);
			}
		}
	}

	/**
	 * 获取后台类目树
	 * @return
	 */
	@Override
	public List<TreeNode> getAllTree() {
		try {
			return categoryTreeCache.get(0L);
		} catch (ExecutionException e) {
			e.printStackTrace();
			return new ArrayList<>();
		}
	}

	//后台类目树暂存内存中，防止频繁查询计算
	private LoadingCache<Long, List<TreeNode>> categoryTreeCache = CacheBuilder.newBuilder()
			.maximumSize(1).expireAfterWrite(100, TimeUnit.SECONDS)
			.build(new CacheLoader() {
				@Override
				public Object load(Object o) throws Exception {
					List<Category> allCategories = baseMapper.getAll();
					//按层级分组
					Map<Integer, List<Category>> levelMap = allCategories.stream().collect(Collectors.groupingBy(Category::getLevel));
					//三级分类
					List<Category> thirdCategories = levelMap.getOrDefault(3, new ArrayList<>());
					Map<Long, List<Category>> thirdCategoryMap = thirdCategories.stream().collect(Collectors.groupingBy(Category::getParentId));
					Map<Long, List<TreeNode>> thirdNodeMap = MapUtil.convert(thirdCategoryMap, k -> k, categories -> toTreeNodeList(categories, true, null));
					//二级分类
					List<Category> secondCategories = levelMap.getOrDefault(2, new ArrayList<>());
					Map<Long, List<Category>> secondCategoryMap = secondCategories.stream().collect(Collectors.groupingBy(Category::getParentId));
					Map<Long, List<TreeNode>> secondNodeMap = MapUtil.convert(secondCategoryMap, k -> k, categories -> toTreeNodeList(categories, true, thirdNodeMap));
					//一级分类
					List<Category> firstCategories = levelMap.getOrDefault(1, new ArrayList<>());
					return toTreeNodeList(firstCategories, true, secondNodeMap);
				}
			});

	/**
	 * 将分类列表转为树节点列表
	 * @param categories
	 * @param onlyLeafCheckable
	 * @return
	 */
	private List<TreeNode> toTreeNodeList(List<Category> categories, boolean onlyLeafCheckable, Map<Long, List<TreeNode>> childrenMap) {
		return categories.stream().map(category -> {
			TreeNode node = new TreeNode();
			node.setTitle(category.getName());
			node.setKey(category.getId());
			node.setValue(category.getId());
			//仅第三级分类可选
			if (onlyLeafCheckable && category.getLevel() < 3) {
				node.setDisableCheckbox(true);
			}
			//设置子树
			if (childrenMap != null) {
				node.setChildren(childrenMap.get(node.getKey()));
			}
			return node;
		}).collect(Collectors.toList());
	}

	/**
	 * 获取类目树
	 * @return
	 */
	@Override
	public List<TreeNode> getCategoryByCache(Long level) {
		try {
			return categoryTreeCache.get(level);
		} catch (ExecutionException e) {
			e.printStackTrace();
			return new ArrayList<>();
		}
	}

}
